﻿//=====================================================================================================
// LocalizationLibrary
// The Localization Library is a collection of reusable software components that provide 
// support for localization. This library enables you to localize WPF, Silverlight and WP7 applications.
// (http://localizationlibrary.codeplex.com)
//=====================================================================================================
// Author: Nicola Gallo (Website: www.nicola.gallo.name, Email: nicolagmt@hotmail.it) 
//=====================================================================================================

namespace ReflectionStudio.Core.Reflection
{
    //.NET References
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Reflection;
    using System.Text;

    //LocalizationLibrary References
    //using ReflectionStudio.LocalizationLibrary.Attributes;

    /// <summary>
    /// Implements a wrapper class of the class <see cref="Type"/>.
    /// </summary>
    public class TypeRef
    {
        //Fields

        private Collection<PropertyInfoRef> _loadedPropertiesInfos;

        //Constructors

        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="Type">Type.</param>
        /// <exception cref="ArgumentNullException">
        /// Thrown whether <paramref name="type"/> parameter is null.
        /// </exception>
        public TypeRef(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("Type parameter shouldn't be null.");
            }
            this.Type = type;
        }

        //Properties

        /// <summary>
        /// Gets wrapped Type.
        /// </summary>
        public Type Type { get; private set; }

        /// <summary>
        /// Gets all the <see cref="PropertyInfoRef"/>s loded.
        /// </summary>
        protected Collection<PropertyInfoRef> LoadedPropertiesInfos
        {
            get
            {
                if (this._loadedPropertiesInfos == null)
                {
                    this._loadedPropertiesInfos = new Collection<PropertyInfoRef>();
                    PropertyInfo[] propertyInfos = this.Type.GetProperties();
                    if (propertyInfos != null)
                    {
                        foreach (PropertyInfo propertyInfo in propertyInfos)
                        {
                            this._loadedPropertiesInfos.Add(new PropertyInfoRef(propertyInfo));
                        }
                    }
                }
                return _loadedPropertiesInfos;
            }
        }

        //Methods

        /// <summary>
        /// Serves as a hash function for <see cref="TypeRef"/> type.
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return this.Type.FullName.GetHashCode();
        }

        /// <summary>
        /// Determines whether the specified <see cref="TypeRef"/> is equals to the current <see cref="TypeRef"/>.
        /// </summary>
        /// <param name="obj">Instance.</param>
        /// <returns>True whether the input instance is equals to the current instance otherwise False.</returns>
        public override bool Equals(object obj)
        {
            if (this == obj)
            {
                return true;
            }
            else if ((obj == null) || (obj.GetType() != this.GetType()))
            {
                return false;
            }
            TypeRef instance = obj as TypeRef;
            return instance.Type.FullName.Equals(this.Type.FullName);
        }

        /// <summary>
        /// Gets all the <see cref="PropertyInfo"/> wrapped in <see cref="PropertyInfoRef"/> defined in the wrapped <see cref="Type"/>.
        /// </summary>
        /// <returns>Gets all the <see cref="PropertyInfo"/> wrapped in <see cref="PropertyInfoRef"/> defined in the wrapped <see cref="Type"/>.</returns>
        public PropertyInfoRef[] GetProperties()
        {
            return this.LoadedPropertiesInfos.ToArray();
        }
    }
}